﻿using System.Runtime.InteropServices;

namespace Godot.core
{
    [StructLayout(LayoutKind.Explicit)]
    public unsafe struct Color
    {
        [FieldOffset(0)] public	float r;
		[FieldOffset(4)] public float g;
		[FieldOffset(8)] public	float b;
		[FieldOffset(12)] public float a;		
		[FieldOffset(0)] public	fixed float components[4];

        public static readonly Color black = new Color(0, 0, 0);

        public Color(float p_r,float p_g,float p_b,float p_a = 1.0f) 
        { 
            r = p_r; g = p_g; b = p_b; a = p_a; 
        }

        public static Color html(string p_color)
        {
            string color = p_color;
            if (color.Length == 0)
                return new Color();
            if (color[0] == '#')
                color = color.Substring(1, color.Length - 1);

            bool alpha = false;

            if (color.Length == 8)
            {
                alpha = true;
            }
            else if (color.Length == 6)
            {
                alpha = false;
            }
            else
            {
                //ERR_EXPLAIN("Invalid Color Code: " + p_color);
                return new Color();
            }

            int a = 255;
            if (alpha)
            {
                a = _parse_col(color, 0);
                if (a < 0)
                {
                    //ERR_EXPLAIN("Invalid Color Code: " + p_color);
                    return new Color();
                }
            }

            int from = alpha ? 2 : 0;

            int r = _parse_col(color, from + 0);
            if (r < 0)
            {
                //ERR_EXPLAIN("Invalid Color Code: " + p_color);
                return new Color();
            }
            
            int g = _parse_col(color, from + 2);
            if (g < 0)
            {
                //ERR_EXPLAIN("Invalid Color Code: " + p_color);
                return new Color();
            }
            
            int b = _parse_col(color, from + 4);
            if (b < 0)
            {
                //ERR_EXPLAIN("Invalid Color Code: " + p_color);
                return new Color();
            }

            return new Color(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
        }

        public static bool html_is_valid(string p_color) 
        {
	        string color = p_color;

	        if (color.Length == 0)
		        return false;

	        if (color[0] == '#')
		        color = color.Substring(1, color.Length - 1);

	        bool alpha = false;

	        if (color.Length == 8) 
            {
		        alpha = true;
	        } 
            else if (color.Length == 6) 
            {
		        alpha = false;
	        } 
            else 
            {
		        return false;
	        }

	        int a = 255;
	        if (alpha) 
            {
		        a = Color._parse_col(color, 0);
		        if (a < 0) 
                {
			        return false;
		        }
	        }

	        int from = alpha ? 2 : 0;

            int r = Color._parse_col(color, from + 0);
	        if (r < 0) 
            {
		        return false;
	        }

            int g = Color._parse_col(color, from + 2);
	        if (g < 0) {
		        return false;
	        }
            int b = Color._parse_col(color, from + 4);
	        if (b < 0) {
		        return false;
	        }

	        return true;
        }

        public static bool operator ==(Color p_c1, Color p_c2)
        {
            return (p_c1.r == p_c2.r) && (p_c1.g == p_c2.g) && (p_c1.b == p_c2.b) && (p_c1.a == p_c2.a);
        }

        public static bool operator !=(Color p_c1, Color p_c2)
        {
            return !(p_c1 == p_c2);
        }

        private static int _parse_col(string p_str, int p_ofs) 
        {
	        int ig = 0;

	        for(int i = 0; i < 2; i++) 
            {
		        int c = p_str[i + p_ofs];
		        int v = 0;

		        if (c >= '0' && c <= '9') 
                {
			        v = c - '0';
		        } 
                else if ( c >= 'a' && c <= 'f') 
                {
			        v = c - 'a';
			        v += 10;
		        } 
                else if (c >= 'A' && c <= 'F') 
                {
			        v = c - 'A';
			        v += 10;
		        } 
                else 
                {
			        return -1;
		        }

		        if (i == 0)
			        ig += v * 16;
		        else
			        ig += v;

	        }
	        return ig;

        }

        public override bool Equals(object obj)
        {
            if (obj is Color)
            {
                return ((Color)obj) == this;
            }
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
}
